package com.gking.centerSystem.utils;


import com.gking.centerSystem.common.BaseContext;
import com.gking.centerSystem.common.Result;
import com.gking.centerSystem.entity.LogsRecord;
import com.gking.centerSystem.service.LogsRecord.LogsRecordService;
import com.gking.centerSystem.utils.commonUtil.CustomEncryptorUtil;
import com.gking.centerSystem.utils.commonUtil.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * 日志记录工具类
 */
@Component
public class LogRecordUtil {

    private final HttpServletRequest request;
    private final HttpServletResponse response;

    @Autowired
    private LogsRecordService logsRecordService0;
    private static LogsRecordService logsRecordService;


    public LogRecordUtil(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    /**
     * 没有这个方法会报空指针，因为还没有注入完成就被注册到 spring 容器中了，
     * 所以这里用一个局部变量保存注入内容，直接使用局部变量
     * <p>
     * 执行顺序： construct>>PostConstruct>>static，
     * 所以在 static 中使用的对象都是在 PostConstruct 里提前组装好的
     */
    @PostConstruct
    private void init() {
        logsRecordService = this.logsRecordService0;
    }


    public void logRecord(String REQUEST_START_TIME_ATTRIBUTE) {
        String token = request.getHeader("Authorization");
        String requestURI = request.getRequestURI();
        // 获取到的请求param参数
        String parameter = getRequestParameter(request);
        // 获取到的请求body参数
        String bodyParam = getRequestBody(request);
        int statusCode = response.getStatus();
        String consumeTime = null;
        String remoteAddr = GetAuthInfoUtil.getClientIp(request);
        String equipmentInfo = request.getHeader("User-Agent");

        Long startTime = (Long) request.getAttribute(REQUEST_START_TIME_ATTRIBUTE);
        if (startTime != null) {
            long durationMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
            consumeTime = durationMillis + "ms";
        }

        // 获取到的请求响应体
        Result deserialize = JsonUtils.deserialize(BaseContext.getResponseBody(), Result.class);
        assert deserialize != null;

        // 在请求完成后执行
        // 可以记录耗时等信息
        LogsRecord logsRecord = new LogsRecord();
        if (token != null) {
            String userId = BaseContext.getCurrentId();
            logsRecord.setAccessUserId(userId);
        }
        if (parameter == null) logsRecord.setAccessPath(requestURI);
        else logsRecord.setAccessPath(requestURI + "?" + parameter);
        logsRecord.setRequestBody(CustomEncryptorUtil.encryption(bodyParam));
        logsRecord.setAccessStatus(statusCode + "");
        logsRecord.setResponseMessage(deserialize.getMessage());
        logsRecord.setResponseStatus(deserialize.getCode());
        logsRecord.setConsumeTime(consumeTime);
        logsRecord.setCreateTime(LocalDateTime.now());
        logsRecord.setIpAddress(remoteAddr);
        logsRecord.setEquipmentInfo(equipmentInfo);

        try {
            logsRecordService.addLogsRecord(logsRecord);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取请求的 param 参数
     *
     * @param request 请求
     * @return param参数字符串
     */
    private String getRequestParameter(HttpServletRequest request) {
        StringBuilder parameterStr = new StringBuilder();

        // 获取请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            String paramName = entry.getKey();
            String[] paramValues = entry.getValue();
            StringBuilder paramValueBuilder = new StringBuilder();
            for (String value : paramValues) paramValueBuilder.append(value);
            parameterStr.append(paramName).append("=").append(paramValueBuilder).append("&");
        }

        if (parameterStr.length() == 0) return null;
        return parameterStr.substring(0, parameterStr.length() - 1);
    }


    /**
     * 获取请求的 body 参数
     *
     * @param request 请求
     * @return body参数字符串
     */
    private String getRequestBody(HttpServletRequest request) {
        StringBuilder data = new StringBuilder();
        String line;
        BufferedReader reader;
        try {
            reader = request.getReader();
            while (null != (line = reader.readLine())) data.append(line);
        } catch (IOException e) {
            return null;
        }
        return data.toString();
    }


}
